{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Visualizing VGG-S filters\n",
    "\n",
    "This is an ipython notebook to generate visualizations of VGG-S filters, for some more info refer to [this blogpost](https://auduno.github.io/2016/06/18/peeking-inside-convnets/).\n",
    "\n",
    "To run this code, you'll need an installation of Caffe with built pycaffe libraries, as well as the python libraries numpy, scipy and PIL. For instructions on how to install Caffe and pycaffe, refer to the installation guide [here](http://caffe.berkeleyvision.org/installation.html). Before running the ipython notebooks, you'll also need to download the [VGG-S model](https://gist.github.com/ksimonyan/fd8800eeb36e276cd6f9), and modify the variables ```pycaffe_root``` to refer to the path of your pycaffe installation (if it's not already in your python path) and ```model_path``` to refer to the path of the downloaded VGG-S caffe model. Also uncomment the line that enables GPU mode if you have built Caffe with GPU-support and a suitable GPU available.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# imports and basic notebook setup\n",
    "from cStringIO import StringIO\n",
    "import numpy as np\n",
    "import os,re,random\n",
    "import scipy.ndimage as nd\n",
    "import PIL.Image\n",
    "import sys\n",
    "from IPython.display import clear_output, Image, display\n",
    "from scipy.misc import imresize\n",
    "\n",
    "pycaffe_root = \"/your/path/here/caffe/python\" # substitute your path here\n",
    "sys.path.insert(0, pycaffe_root)\n",
    "import caffe\n",
    "\n",
    "model_name=\"VGGS\"\n",
    "model_path = '/your/path/here/vggs_model/' # substitute your path here\n",
    "net_fn   = './VGG_CNN_S_deploy_mod.prototxt' # added force_backward : true to prototxt\n",
    "param_fn = model_path + 'VGG_CNN_S.caffemodel'\n",
    "means = np.float32([104.0, 117.0, 123.0])\n",
    "\n",
    "#caffe.set_mode_gpu() # uncomment this if gpu processing is available\n",
    "\n",
    "net = caffe.Classifier(net_fn, param_fn,\n",
    "                       mean = means, # ImageNet mean, training set dependent\n",
    "                       channel_swap = (2,1,0)) # the model has channels in BGR order instead of RGB\n",
    "\n",
    "# a couple of utility functions for converting to and from Caffe's input image layout\n",
    "def preprocess(net, img):\n",
    "    return np.float32(np.rollaxis(img, 2)[::-1]) - net.transformer.mean['data']\n",
    "def deprocess(net, img):\n",
    "    return np.dstack((img + net.transformer.mean['data'])[::-1])\n",
    "\n",
    "def blur(img, sigma):\n",
    "    if sigma > 0:\n",
    "        img[0] = nd.filters.gaussian_filter(img[0], sigma, order=0)\n",
    "        img[1] = nd.filters.gaussian_filter(img[1], sigma, order=0)\n",
    "        img[2] = nd.filters.gaussian_filter(img[2], sigma, order=0)\n",
    "    return img\n",
    "\n",
    "def showarray(a, f, fmt='jpeg'):\n",
    "    a = np.uint8(np.clip(a, 0, 255))\n",
    "    f = StringIO()\n",
    "    PIL.Image.fromarray(a).save(f, fmt)\n",
    "    display(Image(data=f.getvalue()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def make_step(net, step_size=1.5, end='inception_4c/output', clip=True, focus=None, sigma=None):\n",
    "    '''Basic gradient ascent step.'''\n",
    "\n",
    "    src = net.blobs['data'] # input image is stored in Net's 'data' blob\n",
    "\n",
    "    dst = net.blobs[end]\n",
    "    net.forward(end=end)\n",
    "    \n",
    "    one_hot = np.zeros_like(dst.data)\n",
    "    filter_shape = dst.data.shape\n",
    "    if len(filter_shape) > 2:\n",
    "        # backprop only activation in middle of filter\n",
    "        one_hot[0,focus,(filter_shape[2]-1)/2,(filter_shape[3]-1)/2] = 1.\n",
    "    else:\n",
    "        one_hot.flat[focus] = 1.\n",
    "    dst.diff[:] = one_hot\n",
    "    \n",
    "    net.backward(start=end)\n",
    "    g = src.diff[0]\n",
    "    \n",
    "    src.data[:] += step_size/np.abs(g).mean() * g\n",
    "\n",
    "    if clip:\n",
    "        bias = net.transformer.mean['data']\n",
    "        src.data[:] = np.clip(src.data, -bias, 255-bias) \n",
    "        \n",
    "    src.data[0] = blur(src.data[0], sigma)\n",
    "    \n",
    "    dst.diff.fill(0.)\n",
    "\n",
    "def deepdraw(net, base_img, octaves, random_crop=True, visualize=True, focus=None,\n",
    "    clip=True, **step_params):\n",
    "    \n",
    "    # prepare base image\n",
    "    image = preprocess(net, base_img) # (3,224,224)\n",
    "    \n",
    "    # get input dimensions from net\n",
    "    w = net.blobs['data'].width\n",
    "    h = net.blobs['data'].height\n",
    "    \n",
    "    print \"starting drawing\"\n",
    "    src = net.blobs['data']\n",
    "    src.reshape(1,3,h,w) # resize the network's input image size\n",
    "    for e,o in enumerate(octaves):\n",
    "        if 'scale' in o:\n",
    "            # resize by o['scale'] if it exists\n",
    "            image = nd.zoom(image, (1,o['scale'],o['scale']))\n",
    "        _,imw,imh = image.shape\n",
    "        \n",
    "        # select layer\n",
    "        layer = o['layer']\n",
    "        \n",
    "        for i in xrange(o['iter_n']):\n",
    "            if imw > w:\n",
    "                if random_crop:\n",
    "                    # randomly select a crop \n",
    "                    #ox = random.randint(0,imw-224)\n",
    "                    #oy = random.randint(0,imh-224)\n",
    "                    mid_x = (imw-w)/2.\n",
    "                    width_x = imw-w\n",
    "                    ox = np.random.normal(mid_x, width_x*0.3, 1)\n",
    "                    ox = int(np.clip(ox,0,imw-w))\n",
    "                    mid_y = (imh-h)/2.\n",
    "                    width_y = imh-h\n",
    "                    oy = np.random.normal(mid_y, width_y*0.3, 1)\n",
    "                    oy = int(np.clip(oy,0,imh-h))\n",
    "                    # insert the crop into src.data[0]\n",
    "                    src.data[0] = image[:,ox:ox+w,oy:oy+h]\n",
    "                else:\n",
    "                    ox = (imw-w)/2.\n",
    "                    oy = (imh-h)/2.\n",
    "                    src.data[0] = image[:,ox:ox+w,oy:oy+h]\n",
    "            else:\n",
    "                ox = 0\n",
    "                oy = 0\n",
    "                src.data[0] = image.copy()\n",
    "\n",
    "            sigma = o['start_sigma'] + ((o['end_sigma'] - o['start_sigma']) * i) / o['iter_n']\n",
    "            step_size = o['start_step_size'] + ((o['end_step_size'] - o['start_step_size']) * i) / o['iter_n']\n",
    "            \n",
    "            make_step(net, end=layer, clip=clip, focus=focus, \n",
    "                      sigma=sigma, step_size=step_size)\n",
    "            \n",
    "            if visualize:\n",
    "                vis = deprocess(net, src.data[0])\n",
    "                if not clip: # adjust image contrast if clipping is disabled\n",
    "                    vis = vis*(255.0/np.percentile(vis, 99.98))\n",
    "                if i % 1 == 0:\n",
    "                    showarray(vis,\"./filename\"+str(i)+\".jpg\")\n",
    "            \n",
    "            if i % 10 == 0:\n",
    "                print 'finished step %d in octave %d' % (i,e)\n",
    "            \n",
    "            # insert modified image back into original image (if necessary)\n",
    "            image[:,ox:ox+w,oy:oy+h] = src.data[0]\n",
    "        \n",
    "        print \"octave %d image:\" % e\n",
    "        showarray(deprocess(net, image),\"./octave_\"+str(e)+\".jpg\")\n",
    "            \n",
    "    # returning the resulting image\n",
    "    return deprocess(net, image)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "starting drawing\n",
      "finished step 0 in octave 0\n",
      "finished step 10 in octave 0\n",
      "finished step 20 in octave 0\n",
      "finished step 30 in octave 0\n",
      "finished step 40 in octave 0\n",
      "finished step 50 in octave 0\n",
      "finished step 60 in octave 0\n",
      "finished step 70 in octave 0\n",
      "finished step 80 in octave 0\n",
      "finished step 90 in octave 0\n",
      "finished step 100 in octave 0\n",
      "finished step 110 in octave 0\n",
      "finished step 120 in octave 0\n",
      "finished step 130 in octave 0\n",
      "finished step 140 in octave 0\n",
      "finished step 150 in octave 0\n",
      "finished step 160 in octave 0\n",
      "finished step 170 in octave 0\n",
      "finished step 180 in octave 0\n",
      "finished step 190 in octave 0\n",
      "octave 0 image:\n"
     ]
    },
    {
     "data": {
      "image/jpeg": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0a\nHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIy\nMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCADgAOADASIA\nAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA\nAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3\nODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWm\np6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEA\nAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSEx\nBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElK\nU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3\nuLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3iiii\ngAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKA\nCiiigAooooAKKKKACiijNABRSUUCFopKKAFopM0ZoAWikzS5oGFFFFABRRRQAUUUUAFFFFABRRRQ\nAUUUUAFFFFABRRRQAUmaKKACjNJmkJpiFzSZppNJup2AfmjNR7qN1KwEmaM0zdSg0hXH5pc0zNLm\nlcLjqKSjNA7jqKSimMWiiigAooooAKKKKACiiigAooooAKSiigAppNKaaTTACaaTSE1Gzirirkyd\nh5amF6YXGOTUTP6VpyEqVyUvR5lVGlx1polqJKxb2L4enBqpLLkVMr+9c8mYOpqWgaXNRBqXdUqV\n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\nh38OXOORXObVe8ZMHcK665C5OK5sx7L9nx1rDDL3nc46lHms30K90zwBV2ZZuhqFIwjl5j8+OBW6\n9qLuAEcMvSqj2Jdhv5xXTUgnsbQqQSujH8ie83MeBnFbFtp/7hYwB65rRhskSIqqjmrltbiOPpWa\nppDliGxIoQkcaqOR1rQiTA4FQwoQc1aQcU+W5yzbkPRamApqDipAKtaChEAKfSAUtUboWlpKWkUF\nFFFAwooooAKSlooASkNLRQMYRUbCpsU0imNMgK0zZVgim4qrmikRqNtMc5zUxFRuKiSuO5mzg8jF\nZb24MpOK3JI81XNvz0qYxsyW0V7JMEg0ssQEvAq0kO3pUoiB5xWjV2cjjZ6ESRYAqwqcYpVSpVWl\nYVhipiplXilC08CgFEVRTwKQCnCkWkFLRRQWLRRRQAUUUUDCiiigAooooASilpKACkpaKBjSKTFO\nxRimFyMimFamxTSKB3K7JTDHVorTdtBLZAI6cEqXbS7aYrEYWnhacFp2KQrDQKcBSgUtAWClopcU\nhiUtFFABRRRQMKKKKACiiigAooooAKKKKACkpaKAEooxRQAlFLRigBuKTFOxRigBuKXFLilxTENx\nS4paKQBiilxRQAUUUUDCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAMUlLRQAlFLRQAl\nFLRQAYooooAKKKKACiiigAooooAKKKKACiiigD//2Q==\n",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "finished step 0 in octave 1\n",
      "finished step 10 in octave 1\n",
      "finished step 20 in octave 1\n",
      "finished step 30 in octave 1\n",
      "finished step 40 in octave 1\n",
      "finished step 50 in octave 1\n",
      "finished step 60 in octave 1\n",
      "finished step 70 in octave 1\n",
      "finished step 80 in octave 1\n",
      "finished step 90 in octave 1\n",
      "octave 1 image:\n"
     ]
    },
    {
     "data": {
      "image/jpeg": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0a\nHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIy\nMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCADgAOADASIA\nAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA\nAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3\nODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWm\np6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEA\nAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSEx\nBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElK\nU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3\nuLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3iiii\ngAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKA\nCiiigAooooAKKKKACikooAXNJmikzQIWikzRmgBc0uabmjNADqKSigYtFJmloAKKKKACiiigAooo\noAKKKKACiiigAooooAKKKSgAoopKAFzSZpM0hNVYQuaTNNJpC1FgH5ozUe6k3UWAlzS5qLdShqlk\n3JM0tMzS5qbhcdmlpuaWmO4tLTc0tAxaKKKYwooooAKKKKACiiigAooooASiikoAKaTSk00mmAE0\nwtSMcVE0mK1jG5DZIWphaovMpCTVcgkyQvTfMqBn5qJpGHPas56BJ2Lwkp4es1J896sJKM9awkzm\n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\nUUUUAFFFFABRRRQB/9k=\n",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "finished step 0 in octave 2\n",
      "finished step 10 in octave 2\n",
      "finished step 20 in octave 2\n",
      "finished step 30 in octave 2\n",
      "finished step 40 in octave 2\n",
      "finished step 50 in octave 2\n",
      "finished step 60 in octave 2\n",
      "finished step 70 in octave 2\n",
      "finished step 80 in octave 2\n",
      "finished step 90 in octave 2\n",
      "octave 2 image:\n"
     ]
    },
    {
     "data": {
      "image/jpeg": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0a\nHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIy\nMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCADrAOsDASIA\nAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA\nAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3\nODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWm\np6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEA\nAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSEx\nBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElK\nU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3\nuLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3iiii\ngAooooAKKKKACiiigAooooAKKKKACiiigAooooEFFFFAwooooAKKKKACiiigAooooAKKKKACiiig\nAooooAKKKKACiiigAooooAKKSigAzRRSZoELRSZozTAWjNJmjNIB2aM02loAWikooGLRRmigAooo\noAKKKKACiiigAooooAKKKKACiiigAoopKACiikoAWkpM0madhC5ozTc0madgHZozTN1JuosBJmjN\nR7qN1SxXJc0ZpmaXNIVx9GabmlzQFx1FJmigdx1FJRTKFooooAKKKKACiiigAooooAKKKKAEoopK\nACkJoNITTAQmmk0E1GzVaRLHFqQtURek35q+Um5IWppeoy1Rl6mSsJsn304PVQyYpRL71i2ZSqWL\nganhqqq+alDVFyPaomzS5qENTg1Ui1UJgaXNRBqcDTNFIkpaYDThQaJi0tJS0ygooooAKKKKACii\nigApKU0lACUUU0mgAJphNBNMY1SHYRmqB3pZHqu71tFCaHlsnFIrF2IXp61ED+7LnI7CoZbrkQxc\nYGWIqZ1lHRCVNsnkmVeAcnvVZriLOPNwajB8zKoOnU1UuIwUbahJHXNc86kpI1jRg9GXWlZRkEMv\nqKRbjPTrXPNeTW+WUnC9Vq3aanbz/fyhPcVwyrSg/eM6+C93mgb8cp7mrSPnNZMQyq7JlYgZarCS\nt3Bx6+tbQmpbHkTTi7M0Q1KGqur5ANP3d62TCMycNTw1Vg9PVq0R0wkWgaeDUCtUqmg6YskFLTRT\nqDQWigUUDCiiigAooooASkNLSGgBKaTSmmMaBjWNQu1Pc1XkbiqRSIpHquzjv0pJpMA1m3Nwdu1T\n9auUtAkS3d8NxIPyrwKox3J8zrgv61QvLgjcqtjkZrMutRYzoisMkhciuKrVUEVCDk7HXRXsYm8q\nJd7k9BVy42yW6yeW2c4ZUboa5OK9S2VghzKe4rUs9RSIktuAcZIznmuWninN6HS8PyasoaiRGJ3R\nJFywyoPNYEF+Fui0ZPllsFSMkV2GplHtJJEYSFsfdXBriLuGS0PywykOTnb1x61rO1SDaNae2p3F\njeQy7ongJUYBfpmtPyyieZGx8sfdUjNcLpNygMcZLZHDb5Mmuusb3fGqb1wRjFcFObpyOTGYNTjz\nJF+G4Ldcc1Y3e9ZTN5V1t7HkVfVty9a9hNStJHzjTjKzJw1SK1Vg1SI1bpHVTZdQ1OpqrGasrUs6\nokop1MFPpGqFpaSloGFFFFAwoNFJQAUhpaaaAGmmMaeajagCJzVWU1ZeqkpqXKwXKVwetYF5cCIs\nxOMVtXT7VJritbnYBsGsnNscXdlSe93TOwkwQcgHvWbPeeRG9yNrNv8Au56VjXX2v7UrBHaMjGRz\nipUsZ7iLy43KlDluOtcWLpOaO3Cy5ZIltL954hPcStHGjHJFdTp9/ZXkX7mbLBTtfPWuF1+5Omrb\npJAWt1B347mquk6kbi5EljD9nt0GWXk5qZYWbpqUHbyOj2y5mpL5noUOotFciKZX+9jrwak1Sxnk\nkW5E83khTyjfcPuK5q/uJWijuW+ZMjOAQVHrV++m+12MZtbjLEAk7sZx2Na0207eQmrK6e5Wiupo\nZWaYltpzny8ZrpdOvZGHmtwG6L6VxtlewXN62WliuFGDE54JrtrC0iaAFn2zHkjPBrjqqzdztlS9\nzc3BKZYQxPK4NaNvLlck1zy3tvEWXzF9ME1at9RQgY2k134ar+75bHyeOoL2jaN3fUsbZrNimL4r\nQhOa9KOqOeGhejNWkqrFVlKhnTFkwp4qMU8UjZDqUUgoFBQtFFFABSUtJQMDTTTjTTQA01G1SGo2\npMCB6qTVceqsq1lMiRk3Qzmud1G083cDHkHvXVyIpzkVmXuxAcLmsoJt2NMLyyqe9scXHokhf5X2\nqD0rb0rSre3mniJ8yRkySexpk9yVDhCoGKwbLxBCt88S3ambOCtehTwjnFs0xddU52p7Ghq/hmYM\nd0SzQyfN83pWba+GgjRxQRtGGYFuwAr0DRb+PUQIpRlgMZPIFP1CS1hM5BCxJHgAdWNedVj7Ju6N\naU3VSR55rcFsJJIFEksZUqCrhVJFYGkhrhTbb0AZSV56MO2a09SuoXlfdA8ixRlsImdpPrVbQLaN\noYAIXjaXey7xtwe1Z0leMpM6KnuTjBakbW7XAVJIQl1Ecl06kV1enSb7Uc4lHRqx7+5Lwh41ZZkG\n1uwIqLTL7ypVwDsPVfeuOvL3tD2aUVOnZo2J4SzjGfc1e01MHn0p8TWt0gbdtPcGtSzsU2goynPv\nV4edtWfN5rhpxldLQu2yHy1PvWpCOKrRwFVxVuFcV7VH4LngKTUrMuR1ZSq8YqwtDO2DJRTxTBTx\nSN0KKWkpaCxaKKKACkpaSgYGmmnU00ANNManmmGgCF6gcVZYVA4qGjOZSlHasm8TIIrZlXNUZ4C4\n9KzXuu5zOTT0OJ1ON1DKYzg9xXJ2mg2Vvqv2vLtJnhR616fdWzMAroCB3xWM9rGpLeQFUN94V2Us\nS0rHqYGkq2k1oO01bmJcwOFY+tTak88yFGjyyLl3B4qe1ljUbI5AC3XIqDUdojwsmSTyAa467Tlq\nGJaw7cYq3Y4HUG+0ILVHMdxNLl8grlRWjAHjtJifKJhKrFxzxUEuJL+5dwzMgwh9KJ5VSGOSFSyR\nHMmT1NOrHkgooeEl7SfNIrXjl2V41XDNtfBJxVrTrJtzowbPVcd6ismNxM52gQy88Doa6G2CmJWk\nG0xd/WvFq3ctT6anO0SDY0ChsEKODmtO0n4BDkED1qFpoLpSmeX4qK3tZbafDZKnoa78NBOOrPLz\nGp7p1VlduMBmyK3IJAwFc5ZoRtOK3rYcCvSVNJXR8pOV5amlHVharxirC0jWBIKeKaKcKDoQtLSC\nloLFooooAKQ0tFAxKSlpKAGmmkU8000wIWFRMKnIqNhSsDVysyZqJoT17VaYgVUmmIBC1Lg2SqKZ\nTuY1YY6AVUNhHLnnI9KuLE8pyelWo4FUYxzUzjyo3TlBWi7GMdIRh9wZHXFZ97axQMSIwOOprrXB\nRCeM1y+rEDLN+Qrz25yqJM5asak3du5w2PI1CZZOFlyASKrx2TRObYgmJjkt61v3um/bLcSRg7x0\nzWc1pdOFSWYJjjAr0KkOdXOrCtRV7jVWG1hFvDgvnJ74p0940jrBCOn3iKkGnhQVhyWPVqvW2k+U\nmcZZuprj+rXep1yxtlZFawicszN+BrqbO3ElqPMHI71Ba6cI4lG3nNajrsVAtdEaaWiOCvWlU3Jb\nW3GzFaUCYqC2XgVfjSt4XR5zhqTRirCio0FSqKpm0EPFKKQU4UjdC0CiloKCiiigAooooGJSGlNF\nACU0inUhFMZGwqNhUxFRsKZSK0gNVzDk81dZabsqr2NYldY9vQU/aSamCUp4FYz1KsilcABDWBfw\nLIjcc10M4zmsyaPrxXK4e9cVjmI45VfZu+WiWwBfeRmtd7Ub8gVKtuCnIrqWxhUgr3RmwWa7Bgc1\noxWoxgip4bfAxirqQ8DikYlcw4jGB0oSEvgmr4iytOjiwelNITGQxYxV1FpFjxUyrVozsOUVIBSA\nU4UFxQoFOFJS0jRBS0CigYUUUUDCiiigApKWigBKQ0tFAxhFNIqSkIpjRERSbalxSYoKTI8UxhUp\nFNIqWiuYqyLmqkkWa0GWomjqeUfMZhg56U5Yfar3lUCOrSM5O5XWL2qdI6kEdSBKdjFjFSnhKeFp\n4WgVhFWngUoFOAoCwAU4UlOpFJBRRS0DCiiigYUUUUAFFFFABRRRQAlFLSUAFJS0UDEpMU6kxQAw\nikIp+KTFA7kRWmlamxSYpiuQ7KNlS4o20CZGFpwWn4pcUEjQtOApcUuKAsJinUUYpAFLRS0DCiii\ngAooooGFFFFABRRRQAUUUUAFFFFABikpaKAEooooASiloxQA3FGKXFFADcUuKWigBMUYpcUtAhMU\nuKKKACloooAKKKKBhRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAJRS0UAJRRRQAUUUUA\nFFFLQAmKWiigAooooAKKKKACiiigAooooAKKKKAP/9k=\n",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "finished step 0 in octave 3\n",
      "finished step 10 in octave 3\n",
      "finished step 20 in octave 3\n",
      "finished step 30 in octave 3\n",
      "finished step 40 in octave 3\n",
      "octave 3 image:\n"
     ]
    },
    {
     "data": {
      "image/jpeg": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0a\nHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIy\nMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAD3APcDASIA\nAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA\nAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3\nODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWm\np6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEA\nAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSEx\nBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElK\nU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3\nuLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3iiii\ngAooooAKKKKACiiigAooooAKKKKACiiigAooooEFFFFAwooooAKKKKACiiigAooooAKKKKACiiig\nAooooAKKKKACiiigAooooAKKKKACijNJQAtJmiigQUUmaKYC0UmaM0gFzS5ptFADs0UlFAC0UlLm\ngYUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABSUUUAFGaSkzTELSZpM0madgHZpM03NJ\nmiwD80ZpmaN1IVyTNGaZmlBqRXH0U3NLmgLi5pabmloHcWlpuaWgYtFJS0xhRRRQAUUUUAFFFFAB\nRRRQAUUUUAFJRRQAUlFIaYBmmk0E0wmqSEKTSFqYWpparUSbjy1IWqMtTS1JoVyXdRvqAvSeZWbI\n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\nCiiigAooooAKKKKAP//Z\n",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "finished step 0 in octave 4\n",
      "finished step 10 in octave 4\n",
      "finished step 20 in octave 4\n",
      "octave 4 image:\n"
     ]
    },
    {
     "data": {
      "image/jpeg": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0a\nHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIy\nMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAEDAQMDASIA\nAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA\nAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3\nODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWm\np6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEA\nAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSEx\nBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElK\nU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3\nuLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3iiii\ngAooooAKKKKACiiigAooooAKKKKACiiigAooooEFFFFAwooooAKKKKACiiigAooooAKKKKACiiig\nAooooAKKKKACiiigAooooAKKKKACiiigAoopM0ALRmkooAM0UUZoEFFJmjNAC0uabmjNADs0UmaK\nAFopKM0DFooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAopKKACijNJTAM0UmaTN\nAhc0ZpuaM07AOzRmmZozSAfmjNMzS5pCuOzS5puaM0guOzS03NLmgLi0UlLmgYtFJS0xhRRRQAUU\nUUAFFFFABRRRQAUUUUAFFFFABSUUUAFJS000wDNJmimk00hCk0hNNJppaqSFcdmkLUwtTS1Owrkm\n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\nCiiigAooooAKKKKACiiigAooooAKKKKAP//Z\n",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "octaves = [\n",
    "    {\n",
    "        'layer':'conv5',\n",
    "        'iter_n':200,\n",
    "        'start_sigma':2.5,\n",
    "        'end_sigma':1.1,\n",
    "        'start_step_size':12.*0.25,\n",
    "        'end_step_size':10.*0.25,\n",
    "    },\n",
    "    {\n",
    "        'layer':'conv5',\n",
    "        'iter_n':100,\n",
    "        'start_sigma':1.1,\n",
    "        'end_sigma':0.78*1.1,\n",
    "        'start_step_size':10.*0.25,\n",
    "        'end_step_size':8.*0.25\n",
    "    },\n",
    "    {\n",
    "        'layer':'conv5',\n",
    "        'scale':1.05,\n",
    "        'iter_n':100,\n",
    "        'start_sigma':0.78*1.1,\n",
    "        'end_sigma':0.78,\n",
    "        'start_step_size':8.*0.25,\n",
    "        'end_step_size':6.*0.25\n",
    "    },\n",
    "    {\n",
    "        'layer':'conv5',\n",
    "        'scale':1.05,\n",
    "        'iter_n':50,\n",
    "        'start_sigma':0.78*1.1,\n",
    "        'end_sigma':0.40,\n",
    "        'start_step_size':6.*0.25,\n",
    "        'end_step_size':1.5*0.25\n",
    "    },\n",
    "    {\n",
    "        'layer':'conv5',\n",
    "        'scale':1.05,\n",
    "        'iter_n':25,\n",
    "        'start_sigma':0.4,\n",
    "        'end_sigma':0.1,\n",
    "        'start_step_size':1.5*0.25,\n",
    "        'end_step_size':0.5*0.25\n",
    "    }\n",
    "]\n",
    "\n",
    "# get original input size of network\n",
    "original_w = net.blobs['data'].width\n",
    "original_h = net.blobs['data'].height\n",
    "# the background color of the initial image\n",
    "background_color = np.float32([250.0, 250.0, 250.0])\n",
    "# generate initial random image\n",
    "gen_image = np.random.normal(background_color, 8, (original_w, original_h, 3))\n",
    "\n",
    "# which filter in layer to visualize (conv5 has 512 filters)\n",
    "imagenet_class = 10\n",
    "\n",
    "# generate class visualization via octavewise gradient ascent\n",
    "gen_image = deepdraw(net, gen_image, octaves, focus=imagenet_class, \n",
    "                 random_crop=True, visualize=False)\n",
    "\n",
    "# save image\n",
    "#img_fn = '_'.join([model_name, \"deepdraw\", str(imagenet_class)+'.png'])\n",
    "#PIL.Image.fromarray(np.uint8(gen_image)).save('./' + img_fn)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
